#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include "../../lib/srdb1/db.h"
#include "../../lib/srdb1/db_res.h"
#include "../../sr_module.h"
#include "../../dprint.h"
#include "../../ut.h"
#include "../../timer.h"
#include "../../str.h"
#include "../../mem/shm_mem.h"
#include "../../lib/srdb1/db.h"
#include "../../parser/parse_from.h"
#include "../../parser/parse_content.h"
#include "../../parser/contact/parse_contact.h"
#include "../../resolve.h"
#include "../../hashes.h"
#include "../../lib/kmi/mi.h"

#include "../../modules/tm/tm_load.h"

#include "imc_mng.h"
#include "imc_cmd.h"
#include "imc_mem_parse.h"  /* imc_parse_memcached(void) */

MODULE_VERSION

/** header variables */
str imc_hdr_ctype = str_init("Content-Type: text/plain\r\n");
str all_hdrs = {NULL, 0};

/** parameters */
str outbound_proxy   = {NULL, 0};   /* str outbound_proxy = STR_NULL */

str remote_http_url = str_init("http://192.168.1.155:8080/group-web-service/groupchat/groupMember/searchAllMembers");

str remote_http_ip   = str_init("127.0.0.1");
int remote_http_port = 80;
str im_domain        = str_init("127.0.0.1");
int imc_hash_size    = 4;
str remote_memcached_ip   = str_init("127.0.0.1");
int remote_memcached_port = 22133;
int imc_clean_time  = 7;
int imc_repet_time  = 1;


//The default string of these commands
str add_room      = str_init("get groupchat-addgroup\r\n");
str delete_room   = str_init("get groupchat-deletegroup\r\n");
str add_member    = str_init("get groupchat-addmember\r\n");
str delete_member = str_init("get groupchat-deletemember\r\n");

//str add_room      = str_init("get create_room\r\n");
//str delete_room   = str_init("get delete_member\r\n");
//str add_member    = str_init("get groupchat-addmember\r\n");
//str delete_member = str_init("get groupchat-deletemember\r\n");

imc_hentry_p _imc_htable = NULL;

/** module functions */
static int mod_init(void);
static int child_init(int);
static int imc_manager(struct sip_msg*, char *, char *);
static void destroy(void);

/** TM bind */
struct tm_binds tmb;

/** TM callback function */
//void inv_callback( struct cell *t, int type, struct tmcb_params *ps);

/** register the imc_manager function to the cfg file*/
static cmd_export_t cmds[] = {/*{{{*/
	{"imc_manager",  (cmd_function)imc_manager, 0, 0, 0, REQUEST_ROUTE},
	{0,0,0,0,0,0}
};/*}}}*/

static param_export_t params[] = {
    {"reomte_http_url",         PARAM_STR, &remote_http_url},
	{"remote_http_ip",		    PARAM_STR, &remote_http_ip},
	{"remote_http_port",	    INT_PARAM, &remote_http_port},
	{"remote_memcached_ip",	    PARAM_STR, &remote_memcached_ip},
	{"remote_memcached_port",	INT_PARAM, &remote_memcached_port},
	{"outbound_proxy",		    PARAM_STR, &outbound_proxy},
	{"im_domain",	    	    PARAM_STR, &im_domain},
	{"hash_size",			    INT_PARAM, &imc_hash_size},
	{"add_room",	    	    PARAM_STR, &add_room},
	{"delete_room",	    	    PARAM_STR, &delete_room},
	{"add_member",	    	    PARAM_STR, &add_member},
	{"delete_member",	    	PARAM_STR, &delete_member},
	{"clean_time",			    INT_PARAM, &imc_clean_time},
	{"repet_time",			    INT_PARAM, &imc_repet_time},
	{0,0,0}
};

/** modules exports */
struct module_exports exports = {
    "imc",           /*module name */
    DEFAULT_DLFLAGS, /*dlopen flags */
    cmds,            /*exported commands */
    params,          /*exported parameters */
    0,               /*exported statistics */
    0,               /*exported MI functions */
    0,               /*exported pseudo-variables */
    0,               /*extra processes */
    mod_init,        /*mod init */
    0,               /*response handler */
    (destroy_function) destroy, /*destroy function */
    child_init       /*child init */
};

static int mod_init(void)
{/*{{{*/
    LM_DBG("in the imc module of the mod_init function");
    if(imc_hash_size <= 0)
    {
        LM_ERR("invalid hash size\n");
        return -1;
    }

    imc_hash_size = 1 << imc_hash_size;
    if(imc_htable_init() < 0)
    {
        LM_ERR("initiating hash table\n");
        return -1;
    }

    all_hdrs = imc_hdr_ctype;

    if(load_tm_api(&tmb) != 0)
    {
        LM_ERR("unable to load tm api\n");
        return -1;
    }

    register_procs(1);
    return 0;
}/*}}}*/

static int child_init(int rank)
{/*{{{*/
    int pid = -1;

    if(rank != PROC_MAIN)
        return 0;

    pid = fork_process(PROC_NOCHLDINIT, "IMC connect the remote Memcached Server", 1);
    if(pid < 0)
    {
        LM_ERR("failed to register timer routine as process\n");
        return -1;
    }
    else if(pid == 0)
    {
        //deal the http process
        /* 循环接收memcached数据，并解析 */
        imc_parse_memcached();
    }

    return 0;
}/*}}}*/


static void destroy(void)
{/*{{{*/
    imc_htable_destroy();
}/*}}}*/

static int imc_manager(struct sip_msg* msg, char *str1, char *str2)
{/*{{{*/
    str body;
    struct sip_uri from_uri, *pto_uri = NULL, *pfrom_uri = NULL;
    struct to_body *pfrom;
    int ret = -1;

    body.s = get_body(msg);
    if(body.s == 0)
    {
        LM_ERR("can not extract body from msg\n");
        goto error;
    }

    if(!msg->content_length)
    {
        LM_ERR("no Content-Length\n");
        goto error;
    }
    body.len = get_content_length(msg);

    if(body.len <= 0)
    {
        LM_DBG("empty body!\n");
        goto error;
    }
    
    if(parse_sip_msg_uri(msg) < 0)
    {
        LM_ERR("failed to parse r-uri\n");
        goto error;
    }

    pto_uri = &msg->parsed_uri;
    if(parse_from_header(msg) < 0)
    {
        LM_ERR("failed to parse from header\n");
        goto error;
    }

    pfrom = (struct to_body*)msg->from->parsed;
    if(parse_uri(pfrom->uri.s, pfrom->uri.len, &from_uri) < 0)
    {
        LM_ERR("failed to parse from URI\n");
        goto error;
    }

    pfrom_uri = &from_uri;
    
    if(imc_handle_message(msg, &body, pfrom_uri, pto_uri) < 0)
    {
        LM_ERR("failed to handle 'message'\n");
        ret = -200;
        goto error;
    }

    return 1;

error:
    return ret;
        
}/*}}}*/

